package basis.netease.medium;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 7-5 三数之和
 * 给你一个整数数组 nums ，判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ，同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组的数量。
 * 注意：答案中不可以包含重复的三元组（例如[a,b,c]与[c,b,a]为重复），如果无符合要求的三元组，则返回0。
 * 提示：
 * 3 <= nums.length <= 3000
 * -10^5 <= nums[i] <= 10^5
 * 运行有时间、内存限制
 * 输入格式:
 * 一个整数数组，每个元素其间以“空格”分隔
 * 输出格式:
 * 所有符合题目要求三元组的数量，如果无符合要求的三元组，则返回0。
 * 输入样例1:
 * 在这里给出一组输入。例如：
 * -1 0 1 2 -1 -4
 * 输出样例1:
 * 在这里给出相应的输出。例如：
 * 2
 * 解释：
 * nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
 * nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
 * nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
 * 不重复的三元组总共有2组。
 * 输入样例2:
 * 在这里给出一组输入。例如：
 * 0 1 1
 * 输出样例2:
 * 在这里给出相应的输出。例如：
 * 0
 * 解释：无符合条件的三元组
 */
public class Main_5 {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String input = in.nextLine();
        int[] arr = Arrays.stream(input.split(" ")).mapToInt(Integer::parseInt).toArray();
        Arrays.sort(arr);
        System.out.println(compute(arr));
    }

    public static int compute(int[] nums) {
        int count = 0;
        int length = nums.length;
        for (int index = 0; index < length; index++) {
            int vIndex = nums[index];
            // 如果a[i]已经>0，则3个值相加必定>0，直接结束循环
            if (vIndex > 0) {
                break;
            }
            // 如果和上一个值相同，直接跳过，避免重复计算
            if (index > 0 && vIndex == nums[index - 1]) {
                continue;
            }
            // 双指针，从index+1开始，以length-1结束
            int left = index + 1;
            int right = length - 1;
            // 如果nums[right]已经<0，则3个值相加必定<0，直接结束循环
            while (left < right && nums[right] >= 0) {
                int vLeft = nums[left];
                int vRight = nums[right];
                int sum = vIndex + vLeft + vRight;
                if (sum == 0) {
                    count++;
                    // 如果left的值和left++的值相同，则继续往下找，直到找到不同的值为止，避免重复计算
                    do {
                        left++;
                    } while (left < right && vLeft == nums[left]);
                } else if (sum > 0) {
                    // 如果right的值和right--的值相同，则继续往下找，直到找到不同的值为止，避免重复计算
                    do {
                        right--;
                    } while (left < right && vRight == nums[right]);
                } else {
                    do {
                        left++;
                    } while (left < right && vLeft == nums[left]);
                }
            }
        }
        return count;
    }

}
